import traceback
import time

from django.core.exceptions import ObjectDoesNotExist
from django.http.response import HttpResponse, HttpResponseNotFound
from django.utils.deprecation import MiddlewareMixin
from django.db import connection
from django.conf import settings

from .utils import json_response
from apps.account.models import User


class HandleExceptionMiddleware(MiddlewareMixin):
    """
    处理试图函数异常
    """

    def process_exception(self, request, exception):
        traceback.print_exc()
        if isinstance(exception, ObjectDoesNotExist):
            return json_response(error='Resource not found')
        else:
            return json_response(error='%s' % exception)


class CrossDomainAccessMiddleware(MiddlewareMixin):
    """
    跨域访问
    """

    def process_request(self, request):
        if request.method == 'OPTIONS':
            response = HttpResponse()
            response['Access-Control-Allow-Origin'] = '*'
            response['Access-Control-Allow-Headers'] = 'Content-Type, X-TOKEN'
            response['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
            return response

    def process_response(self, request, response):
        response.setdefault('Access-Control-Allow-Origin', '*')
        response.setdefault('Access-Control-Allow-Headers', 'Content-Type, X-TOKEN')
        return response


class AuthenticationMiddleware(MiddlewareMixin):
    """
    登录验证
    """

    def process_request(self, request):
        access_token = request.META.get('HTTP_X_TOKEN') or request.GET.get('x-token')
        if access_token and len(access_token) == 32:
            user = User.objects.filter(access_token=access_token).first()
            if user and user.token_expired >= time.time() and user.is_active:
                request.user = user
                user.token_expired = time.time() + 8 * 60 * 60
                user.save()
                return None
        if request.path in settings.AUTHENTICATION_EXCLUDES:
            return None
        if any(x.match(request.path) for x in settings.AUTHENTICATION_EXCLUDES if hasattr(x, 'match')):
            return None
        response = json_response(error="验证失败，请重新登录")
        response.status_code = 401
        return response


class DatabaseEchoMiddleware(MiddlewareMixin):
    """
    打印请求产生的所有数据库sql操作（需要启用Debug模式）
    """

    def process_response(self, request, response):
        for i, q in enumerate(connection.queries):
            print(i + 1, q['time'], q['sql'])
        return response
